package org.ediba.siri.core.model.service;

import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import org.ediba.siri.core.Filter;
import org.ediba.siri.core.Util;
import org.ediba.siri.core.model.data.ModelAddressDao;
import org.ediba.siri.core.model.data.ModelDao;
import org.ediba.siri.core.model.data.ModelEmailDao;
import org.ediba.siri.core.model.data.ModelFeatureDao;
import org.ediba.siri.core.model.data.ModelModelDao;
import org.ediba.siri.core.model.data.ModelNoteDao;
import org.ediba.siri.core.model.data.ModelPhoneDao;
import org.ediba.siri.core.model.data.ModelRelationshipDao;
import org.ediba.siri.core.model.data.ModelSchoolDao;
import org.ediba.siri.core.model.data.ModelVisitDao;
import org.ediba.siri.core.model.domain.Model;
import org.ediba.siri.core.model.domain.ModelAddress;
import org.ediba.siri.core.model.domain.ModelEmail;
import org.ediba.siri.core.model.domain.ModelFeature;
import org.ediba.siri.core.model.domain.ModelModel;
import org.ediba.siri.core.model.domain.ModelModelId;
import org.ediba.siri.core.model.domain.ModelNote;
import org.ediba.siri.core.model.domain.ModelPhone;
import org.ediba.siri.core.model.domain.ModelRelationship;
import org.ediba.siri.core.model.domain.ModelSchool;
import org.ediba.siri.core.model.domain.ModelVisit;
import org.ediba.siri.core.request.data.RequestDao;

public class DefaultModelService implements ModelService{

	private ModelDao modelDao;
	public void setModelDao(ModelDao modelDao) {this.modelDao = modelDao;}
	
	private ModelModelDao modelModelDao;
	public void setModelModelDao(ModelModelDao modelModelDao) {this.modelModelDao = modelModelDao;}
	
	private ModelAddressDao modelAddressDao;
	public void setModelAddressDao(ModelAddressDao modelAddressDao) {this.modelAddressDao = modelAddressDao;}
	
	private ModelPhoneDao modelPhoneDao;
	public void setModelPhoneDao(ModelPhoneDao modelPhoneDao) {this.modelPhoneDao = modelPhoneDao;}
	
	private ModelFeatureDao modelFeatureDao;
	public void setModelFeatureDao(ModelFeatureDao modelFeatureDao) {this.modelFeatureDao = modelFeatureDao;}
	
	private ModelNoteDao modelNoteDao;
	public void setModelNoteDao(ModelNoteDao modelNoteDao) {this.modelNoteDao = modelNoteDao;}
	
	private ModelRelationshipDao modelRelationshipDao;
	public void setModelRelationshipDao(ModelRelationshipDao modelRelationshipDao) {this.modelRelationshipDao = modelRelationshipDao;}
	
	private ModelSchoolDao modelSchoolDao;
	public void setModelSchoolDao(ModelSchoolDao modelSchoolDao) {this.modelSchoolDao = modelSchoolDao;}
	
	private ModelEmailDao modelEmailDao;
	public void setModelEmailDao(ModelEmailDao modelEmailDao) {this.modelEmailDao = modelEmailDao;}
	
	private RequestDao requestDao;
	public void setRequestDao(RequestDao requestDao) {this.requestDao = requestDao;}
	
	private ModelVisitDao modelVisitDao;
	public void setModelVisitDao(ModelVisitDao modelVisitDao) {this.modelVisitDao = modelVisitDao;}
	/**********************************MODEL**********************************/
	
	@Override
	public Model create() {
		Model model = new Model();
		return this.modelDao.merge(model);
	}
	
	@Override
	public Model retrieve(int id) {
		return this.modelDao.findById(id);
	}
	
	@Override
	public Model update(Model model) {
		return this.modelDao.merge(model);
	}
	
	@Override
	public boolean delete(int id) {
		Model model = this.modelDao.findById(id);
		if (model != null){
			this.modelDao.delete(model);
			return true;
		}
		else
			return false;
	}
	

	@Override
	public List<Model> retrieve(String[] name, int start, int limit) {
		Collection<Map<Filter,Object>> filters = new HashSet<Map<Filter,Object>>();
		Map<Filter,Object> filter ;
		
		for (String s : name) {
			filter = new HashMap<Filter,Object>(1);
			filter.put(Filter.FIRSTNAME, s);
			filters.add(filter);
		
			filter = new HashMap<Filter,Object>(1);
			filter.put(Filter.LASTNAME, s);
			filters.add(filter);
		}
		
		return this.modelDao.findByFilters(filters, "firstName", true, start, limit);
	}
	
	@Override
	public List<Model> retrieve(Map<Filter, Object> filters, String sort, boolean dir, int start, int limit) {
		Collection<Map<Filter,Object>> _filters = new HashSet<Map<Filter,Object>>(1);
		_filters.add(filters);
		return this.modelDao.findByFilters(_filters, sort, dir, start, limit);
	}

	@Override
	public List<Model> retrieve(Map<Filter, Object> filters, String sort, boolean dir) {
		Collection<Map<Filter,Object>> _filters = new HashSet<Map<Filter,Object>>(1);
		_filters.add(filters);
		return this.modelDao.findByFilters(_filters, sort, dir);
	}
	
	@Override
	public int retrieveCount(Map<Filter, Object> filters) {
		Collection<Map<Filter,Object>> _filters = new HashSet<Map<Filter,Object>>(1);
		_filters.add(filters);
		return this.modelDao.findByFiltersCount(_filters);
	}

	@Override
	public int retrieveCount() {
		return this.modelDao.getAllCount();
	}
	
	/********************************MODEL-MODEL*********************************/
	
	@Override
	public ModelModel modelModelCreate(int idModelA, int idModelB, Model modelByIdModelB, Model modelByIdModelA, ModelRelationship modelrelationship) {
		ModelModelId id = new ModelModelId(idModelA, idModelB);
		ModelModel modelModel = new ModelModel(id, modelByIdModelB, modelByIdModelA, modelrelationship);
		return this.modelModelDao.merge(modelModel);
	}

	@Override
	public ModelModel modelModelRetrieve(ModelModelId id) {
		return this.modelModelDao.findById(id);
	}

	@Override
	public ModelModel modelModelUpdate(ModelModel modelModel) {
		return this.modelModelDao.merge(modelModel);
	}

	@Override
	public boolean modelModelDelete(ModelModelId id) {
		ModelModel modelModel = this.modelModelDao.findById(id);
		if (modelModel != null){
			this.modelModelDao.delete(modelModel);
			return true;
		}
		else
			return false;
	}

	@Override
	public List<ModelModel> modelModelRetrieve() {
		return this.modelModelDao.getAll(null, false);
	}
	
	@Override
	public List<ModelModel> modelModelretrieveForIdModelB(int idModelB) {
		return this.modelModelDao.findByFilters(Util.simpleFilter(Filter.MODELB_ID, idModelB), null, false);
		
	}
	/****************************MODEL-RELATIONSHIP******************************/
	@Override
	public ModelRelationship relationshipCreate(String name, boolean message) {
		ModelRelationship instance = new ModelRelationship(name,message);
		return this.modelRelationshipDao.merge(instance);
	}

	@Override
	public ModelRelationship relationshipRetrieve(int id) {
		return this.modelRelationshipDao.findById(id);
	}

	@Override
	public ModelRelationship relationshipUpdate(ModelRelationship modelRelationship) {
		return this.modelRelationshipDao.merge(modelRelationship);
	}

	@Override
	public boolean relationshipDelete(int id) {
		ModelRelationship modelRelationship = this.modelRelationshipDao.findById(id);
		if (modelRelationship != null){
			this.modelRelationshipDao.delete(modelRelationship);
			return true;
		}
		else
			return false;
	}

	@Override
	public List<ModelRelationship> relationshipRetrieve() {
		return this.modelRelationshipDao.getAll(null, false);
	}

	@Override
	public List<ModelRelationship> relationshipRetrieve(String sort,boolean dir, int start, int limit) {
		return this.modelRelationshipDao.getAll(sort, dir, start, limit);
	}
	
	/****************************MODEL-ADDRESS******************************/
	@Override
	public ModelAddress addressCreate(String street, Integer number, int idModel) {
		ModelAddress instance = new ModelAddress();
		instance.setStreet(street);
		instance.setNumber(number);
		instance.setModel(this.modelDao.findById(idModel));
		return this.modelAddressDao.merge(instance);
	}

	@Override
	public ModelAddress addressRetrieve(int id) {
		return this.modelAddressDao.findById(id);
	}

	@Override
	public ModelAddress addressUpdate(ModelAddress modelAddress) {
		return this.modelAddressDao.merge(modelAddress);
	}

	@Override
	public boolean addressDelete(int id) {
		return this.modelAddressDao.delete(id);
	}

	/****************************MODEL-PHONE******************************/
	@Override
	public ModelPhone phoneCreate(String number, int idModel) {
		ModelPhone instance = new ModelPhone();
		instance.setNumber(number);
		instance.setModel(this.modelDao.findById(idModel));
		return this.modelPhoneDao.merge(instance);
	}

	@Override
	public ModelPhone phoneRetrieve(int id) {
		return this.modelPhoneDao.findById(id);
	}

	@Override
	public ModelPhone phoneUpdate(ModelPhone modelPhone) {
		return this.modelPhoneDao.merge(modelPhone);
	}

	@Override
	public boolean phoneDelete(int id) {
		return this.modelPhoneDao.delete(id);
	}

	/****************************MODEL-FEATURE******************************/
	@Override
	public ModelFeature featureCreate(String feature, int idModel) {
		ModelFeature instance = new ModelFeature();
		instance.setFeature(feature);
		instance.setModel(this.modelDao.findById(idModel));
		return this.modelFeatureDao.merge(instance);
	}

	@Override
	public ModelFeature featureRetrieve(int id) {
		return this.modelFeatureDao.findById(id);
	}

	@Override
	public ModelFeature featureUpdate(ModelFeature modelFeature) {
		return this.modelFeatureDao.merge(modelFeature);
	}

	@Override
	public boolean featureDelete(int id) {
		return this.modelFeatureDao.delete(id);
	}

	/****************************MODEL-NOTE******************************/
	@Override
	public ModelNote noteCreate(String text, int idModel) {
		ModelNote instance = new ModelNote();
		instance.setText(text);
		instance.setModel(this.modelDao.findById(idModel));
		return this.modelNoteDao.merge(instance);
	}

	@Override
	public ModelNote noteRetrieve(int id) {
		return this.modelNoteDao.findById(id);
	}

	@Override
	public ModelNote noteUpdate(ModelNote modelNote) {
		return this.modelNoteDao.merge(modelNote);
	}

	@Override
	public boolean noteDelete(int id) {
		return this.modelNoteDao.delete(id);
	}

	@Override
	public ModelSchool modelSchoolCreate(String name) {
		ModelSchool instance = new ModelSchool();
		instance.setName(name);
		return this.modelSchoolDao.merge(instance);
	}

	@Override
	public ModelSchool modelSchoolRetrieve(int id) {
		return this.modelSchoolDao.findById(id);
	}

	@Override
	public ModelSchool modelSchoolUpdate(ModelSchool modelSchool) {
		return this.modelSchoolDao.merge(modelSchool);
	}

	@Override
	public boolean modelSchoolDelete(int id) {
		return this.modelSchoolDao.delete(id);
	}
	@Override
	public List<ModelSchool> modelSchoolRetrieve() {
		return this.modelSchoolDao.getAll("name", true);
	}
	@Override
	public List<ModelSchool> modelSchoolRetrieve(Map<Filter, Collection<Object>> filters,
			String sort, boolean dir) {
		return this.modelSchoolDao.findByFilters(filters, sort, dir);
	}
	@Override
	public ModelEmail emailCreate(String email, int idModel) {
		ModelEmail instance = new ModelEmail();
		instance.setEmail(email);
		instance.setModel(this.modelDao.findById(idModel));
		return this.modelEmailDao.merge(instance);
	}
	@Override
	public ModelEmail emailRetrieve(int id) {
		return this.modelEmailDao.findById(id);
	}
	@Override
	public ModelEmail emailUpdate(ModelEmail modelEmail) {
		return this.modelEmailDao.merge(modelEmail);
	}
	@Override
	public boolean emailDelete(int id) {
		return this.modelEmailDao.delete(id);
	}
	@Override
	public List<ModelEmail> emailRetrieve() {
		return this.modelEmailDao.getAll("email", true);
	}
	/****************************MODELVISIT******************************/
	@Override
	public ModelVisit visitCreate(int idModel, int idRequest, Date date,
			boolean delivered) {
		ModelVisit modelVisit = new ModelVisit();
		modelVisit.setDate(date);
		modelVisit.setDelivered(delivered);
		modelVisit.setModel(this.modelDao.findById(idModel));
		modelVisit.setRequest(this.requestDao.findById(idRequest));
		return this.modelVisitDao.merge(modelVisit);
	}
	@Override
	public ModelVisit visitRetrieve(int id) {
		return this.modelVisitDao.findById(id);
	}
	@Override
	public ModelVisit visitUpdate(ModelVisit modelVisit) {
		return this.modelVisitDao.merge(modelVisit);
	}
	@Override
	public boolean visitDelete(int id) {
		return this.modelVisitDao.delete(id);
	}

}
